<?php

Junction_FileCabinet::using("Junction_Expression_Exception");
Junction_FileCabinet::using("Junction_Expression_Grammar");

/**
 * Abstract Recursive Descent Parser
 * 
 * This class lays the frame work for a concrete implementation  
 * of a recursive descent parser.
 * 
 * @author Patrick J. Mizer <patrick.mizer@gmail.com>
 * @package junction.expression
 */
abstract class Junction_Expression_RecursiveDescent
{	
	/**
	 * Tokens of the expression
	 * 
	 * @var array
	 */
	private $_expressionArray;
	
	/**
	 * Internal expression array pointer
	 * 
	 * @var int
	 */
	private $_index;
	
	/**
	 * Convenience method to parse the expression into a token array.
	 * 
	 * @param string expression
	 * @return array token array
	 */
	protected final function _prepareRawExpression($expression, array $tokens)
	{
		$this->_index = 0;
		
		$replace = $tokens;	
		
		foreach($replace as $token){
			$replaceWith[] = ' ' . $token . ' ';
		}
		
		$tokenArray = explode(' ', str_replace($replace, $replaceWith, $expression));
		
		$retArray = array();
		foreach($tokenArray as $token){
			$token = trim($token);
			if($token != null){
				$retArray[] = trim($token);
			}
		}
		
		$retArray[] = Junction_Expression_Grammar::$endOfExpressionToken;
		
		$this->_expressionArray = $retArray;
	}
	
	/**
	 * Get next token in expression.
	 * 
	 * @return string token
	 */
	protected final function _next()
	{
		return $this->_expressionArray[$this->_index];
	}	
	
	/**
	 * Expect particular token, if expected token is not next throw
	 * exception.
	 * 
	 * @param string token.
	 * @throws Junction_Expression_Exception invalid token.
	 */
	protected final function _expect($token)
	{
		if ($this->_next() == $token) {
			$this->_consume();
		} else
			throw new Junction_Expression_Exception('Invalid Token encountered: "' . $this->_next . '", expected: "' . $token . '"');	
	} 
	
	/**
	 * Consume next token.
	 * 
	 * @return void
	 */
	protected final function _consume()
	{
	 	++ $this->_index;
	}		
	
	/**
	 * Get expression array.
	 * 
	 * @return array
	 */
	protected function _getExpressionArray()
	{
		return $this->_expressionArray;
	}
}
?>
